use actix_web::HttpResponse;
use rbatis::{Page, rbdc, sql::{self, PageRequest}};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ResData<T> {
    success: bool,
    total: Option<u64>,
    message: Option<String>,
    data: Option<Vec<T>>,
    page_size: Option<u64>,
    current: Option<u64>,
}

impl<T> Default for ResData<T> {
    fn default() -> Self {
        Self {
            success: Default::default(),
            total: Default::default(),
            message: Default::default(),
            data: Default::default(),
            page_size: Default::default(),
            current: Default::default(),
        }
    }
}

impl<T> ResData<T>
    where
        T: Serialize,
{
    pub fn from_page<U: Into<T> + Send + Sync>(page: Result<Page<U>, rbdc::Error>) -> Self {
        let mut res_data = ResData::<T>::default();
        match page {
            Ok(page) => {
                res_data.success = true;
                res_data.total = Some(page.total);
                res_data.data = Some(page.records.into_iter().map(U::into).collect());
                res_data.page_size = Some(page.page_size);
                res_data.current = Some(page.page_no);
            }
            Err(e) => {
                res_data.success = false;
                res_data.message = Some(e.to_string());
            }
        }
        res_data
    }

    pub fn from_data<U: Into<T>>(data: Result<Vec<U>, rbdc::Error>) -> Self {
        let mut res_data = ResData::<T>::default();
        match data {
            Ok(data) => {
                res_data.success = true;
                res_data.data = Some(data.into_iter().map(U::into).collect());
            }
            Err(e) => {
                res_data.success = false;
                res_data.message = Some(e.to_string());
            }
        }
        res_data
    }

    pub fn trans(mut self, f: fn(&mut T)) -> Self {
        let _ = self.data.iter_mut().map(|d| d.iter_mut().for_each(f));
        self
    }

    pub fn resp_json(&self) -> HttpResponse {
        HttpResponse::Ok().json(self)
    }
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(rename_all = "camelCase")]
pub struct QueryPage {
    pub current: Option<u64>,
    pub page_size: Option<u64>,
}

impl From<&QueryPage> for PageRequest {
    fn from(arg: &QueryPage) -> Self {
        PageRequest::new(arg.current.unwrap_or(1), arg.page_size.unwrap_or(10))
    }
}

pub enum Ret {
    Success = 0,
    Fail = 1,
    UsernameRepeat = 2,
    FingerRepeat = 3,
    UserNotExists = 4,
    FingerNotExists = 5,
    VerifyFailure = 6,
    IdentifyFailure = 7,
    ServiceStop = 8,
    AppNotExists = 9,
    AppPwdError = 10,
    LicenseError = 11,
    UsernameEmpty = 12,
    TokenExpire = 13,
    Unauthorized = 14,
    IcNotExistst = 15,
    CarNumberNotExists = 16,
    PhoneNotExists = 17,
    CarNumberExists = 18,
    IcExistst = 19,
    PhoneExists = 20,
    UsernameFormatError = 21,
    FingerDataError = 22,
    SignError = 23,
    AppExpire = 24,
    LicenseTimeExpire = 25,
    LicenseUserCountLimit = 26,
    LicenseServerMacAddrError = 27,
    TimeStampExpire = 28,
    PermissionDenied = 29,
    FileNotFound = 30,
    VerifyDataNull = 31,
    FaceNotSupport = 32,
    IrisNotSupport = 33,
    PhoneNull = 34,
    PhoneHasBeenVerified = 35,
    PhoneMsgRepeatSend = 36,
    PhoneVerifyFail = 37,
    DeviceDisabled = 38,
}

impl Copy for Ret {}

impl Clone for Ret {
    fn clone(&self) -> Ret {
        *self
    }
}

impl Ret {
    pub fn to_u32(&self) -> u32 {
        *self as u32
    }

    pub fn to_string(&self) -> &str {
        match self {
            Ret::Success => "OK",
            Ret::Fail => "Fail",
            Ret::UsernameRepeat => "UsernameRepeat",
            Ret::FingerRepeat => "FingerRepeat",
            Ret::UserNotExists => "UserNotExists",
            Ret::FingerNotExists => "FingerNotExists",
            Ret::VerifyFailure => "VerifyFailure",
            Ret::IdentifyFailure => "IdentifyFailure",
            Ret::ServiceStop => "ServiceStop",
            Ret::AppNotExists => "AppNotExists",
            Ret::AppPwdError => "AppPwdError",
            Ret::LicenseError => "LicenseError",
            Ret::UsernameEmpty => "UsernameEmpty",
            Ret::TokenExpire => "TokenExpire",
            Ret::Unauthorized => "Unauthorized",
            Ret::IcNotExistst => "IcNotExistst",
            Ret::CarNumberNotExists => "CarNumberNotExists",
            Ret::PhoneNotExists => "PhoneNotExists",
            Ret::CarNumberExists => "CarNumberExists",
            Ret::IcExistst => "IcExistst",
            Ret::PhoneExists => "PhoneExists",
            Ret::UsernameFormatError => "UsernameFormatError",
            Ret::FingerDataError => "FingerDataError",
            Ret::SignError => "SignError",
            Ret::AppExpire => "AppExpire",
            Ret::LicenseTimeExpire => "LicenseTimeExpire",
            Ret::LicenseUserCountLimit => "LicenseUserCountLimit",
            Ret::LicenseServerMacAddrError => "LicenseServerMacAddrError",
            Ret::TimeStampExpire => "TimeStampExpire",
            Ret::PermissionDenied => "PermissionDenied",
            Ret::FileNotFound => "FileNotFound",
            Ret::VerifyDataNull => "VerifyDataNull",
            Ret::FaceNotSupport => "FaceNotSupport",
            Ret::IrisNotSupport => "IrisNotSupport",
            Ret::PhoneNull => "PhoneNull",
            Ret::PhoneHasBeenVerified => "PhoneHasBeenVerified",
            Ret::PhoneMsgRepeatSend => "PhoneMsgRepeatSend",
            Ret::PhoneVerifyFail => "PhoneVerifyFail",
            Ret::DeviceDisabled => "DeviceDisabled",
        }
    }
}
